package com.example.demo.service.exam.impl;

import com.example.demo.domain.CombineClause;
import com.example.demo.domain.PageResult;
import com.example.demo.domain.SingleClause;
import com.example.demo.domain.exam.ExamUserScore;
import com.example.demo.domain.exam.QueryModel;
import com.example.demo.domain.exam.condition.ConditionParser;
import com.example.demo.domain.exam.condition.ExamUserScoreCondition;
import com.example.demo.enums.SubmitType;
import com.example.demo.exception.ExceptionUtils;
import com.example.demo.mapper.ExamUserScoreMapper;
import com.example.demo.service.exam.ExamClassService;
import com.example.demo.service.exam.ExamUserScoreService;
import com.example.demo.service.impl.BaseServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ExamUserScoreServiceImpl extends BaseServiceImpl<ExamUserScoreMapper, ExamUserScore> implements ExamUserScoreService {

    private final ExamUserScoreMapper mapper;

    private final ExamClassService examClassService;

    @Override
    public PageResult<ExamUserScore> page(QueryModel<ExamUserScoreCondition> model) {
        ExamUserScoreCondition condition = Optional.ofNullable(model.getCondition()).orElse(new ExamUserScoreCondition());
        if (condition.getExamId() == null) {
            throw ExceptionUtils.exception("考试标识不能为空");
        }
        PageResult<ExamUserScore> result = super.selectPage(ConditionParser.parser(model.getCondition()), model.getPaging(), model.getSorts());
        // 计算考试时长，
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        result.getData().forEach(e ->{
                    if(e.getSubmitTime() != null && e.getEnterTime() != null)
                        e.setTime((e.getSubmitTime().getTime() - e.getEnterTime().getTime()) / 60 / 1000);
        });

        List<Long> classIds = result.getData().stream().map(ExamUserScore::getClassId).collect(Collectors.toList());
        Map<Long, String> map = examClassService.getNameMapByIds(classIds);
        result.getData().forEach(e ->
                e.setClassName(map.getOrDefault(e.getClassId(), ""))
        );
        return result;
    }

    @Override
    public List<ExamUserScore> getByExamId(Long examId) {
        if (examId == null) {
            throw ExceptionUtils.exception("考试标识不能为空");
        }
        return super.selectList(SingleClause.equal("exam_id", examId));
    }

    @Override
    public ExamUserScore getByExamUserId(Long examId, Long userId) {
        if (examId == null) {
            throw ExceptionUtils.exception("考试标识不能为空");
        }
        if (userId == null) {
            throw ExceptionUtils.exception("用户标识不能为空");
        }
        return super.selectOne(CombineClause.and(
                SingleClause.equal("exam_id", examId),
                SingleClause.equal("user_id", userId))
        );
    }

    @Override
    public void insertOrUpdate(ExamUserScore entity) {
        valid(entity);
        super.saveOrUpdate(entity);
    }

    @Override
    public void insertList(List<ExamUserScore> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        super.saveBatch(list);
    }

    private void valid(ExamUserScore entity) {
        Optional.ofNullable(entity.getUserId()).orElseThrow(() -> ExceptionUtils.exception("用户标识不能为空"));
        Optional.ofNullable(entity.getClassId()).orElseThrow(() -> ExceptionUtils.exception("班级标识不能为空"));
        Optional.ofNullable(entity.getExamId()).orElseThrow(() -> ExceptionUtils.exception("考试标识不能为空"));
    }

    @Override
    public void deleteByExamUserId(Long examId, Long userId) {
        Optional.ofNullable(userId).orElseThrow(() -> ExceptionUtils.exception("用户标识不能为空"));
        Optional.ofNullable(examId).orElseThrow(() -> ExceptionUtils.exception("班级标识不能为空"));
        HashMap<String, Object> map = new HashMap<>();
        map.put("score", 0d);
        map.put("enter_time", null);
        map.put("submit_time", null);
        map.put("ip", "");
        map.put("time", null);
        map.put("status", null);
        map.put("type", SubmitType.NOT_SUBMIT);
        super.modify(map, CombineClause.and(
                SingleClause.equal("user_id", userId),
                SingleClause.equal("exam_id", examId)
        ));
    }

    @Override
    public void insertOrUpdateList(List<ExamUserScore> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        super.saveOrUpdateBatch(list);
    }

    @Override
    public List<ExamUserScore> getByExamUserId(List<Long> examIds, Long userId) {
        Optional.ofNullable(userId).orElseThrow(() -> ExceptionUtils.exception("用户标识不能为空"));
        if (CollectionUtils.isEmpty(examIds)) {
            return Collections.emptyList();
        }
        return super.selectList(CombineClause.and(
                SingleClause.equal("user_id", userId),
                SingleClause.in("exam_id", examIds.toArray(new Object[0])))
        );
    }

}
